<?php

/**
 *  Methods used with the {@link resize()} method.
 */
define('ZEBRA_IMAGE_BOXED', 0);
define('ZEBRA_IMAGE_NOT_BOXED', 1);
define('ZEBRA_IMAGE_CROP_TOPLEFT', 2);
define('ZEBRA_IMAGE_CROP_TOPCENTER', 3);
define('ZEBRA_IMAGE_CROP_TOPRIGHT', 4);
define('ZEBRA_IMAGE_CROP_MIDDLELEFT', 5);
define('ZEBRA_IMAGE_CROP_CENTER', 6);
define('ZEBRA_IMAGE_CROP_MIDDLERIGHT', 7);
define('ZEBRA_IMAGE_CROP_BOTTOMLEFT', 8);
define('ZEBRA_IMAGE_CROP_BOTTOMCENTER', 9);
define('ZEBRA_IMAGE_CROP_BOTTOMRIGHT', 10);

// this enables handling of partially broken JPEG files without warnings/errors
ini_set('gd.jpeg_ignore_warning', true);

/**
 *  A compact, lightweight, object-oriented image manipulation library written in and for PHP, that provides methods
 *  for performing several types of image manipulation operations. It doesn't require any external libraries other than
 *  the GD2 extension (with which PHP usually comes precompiled with).
 *
 *  The code is heavily commented and generates no warnings/errors/notices when PHP's error reporting level is set to
 *  E_ALL.
 *
 *  With this library you can rescale, flip, rotate and crop images. It supports loading and saving images in the GIF,
 *  JPEG and PNG formats and preserves transparency for GIF, PNG and PNG24.
 *
 *  The cool thing about it is that it can resize images to exact given width and height and still maintain aspect
 *  ratio.
 *
 *  Visit {@link http://stefangabos.ro/php-libraries/zebra-image/} for more information.
 *
 *  For more resources visit {@link http://stefangabos.ro/}
 *
 *  @author     Stefan Gabos <contact@stefangabos.ro>
 *  @version    2.2.3 (last revision: July 14, 2013)
 *  @copyright  (c) 2006 - 2013 Stefan Gabos
 *  @license    http://www.gnu.org/licenses/lgpl-3.0.txt GNU LESSER GENERAL PUBLIC LICENSE
 *  @package    Zebra_Image
 */
class Zebra_Image
{


	private $_r;
	private $_g;
	private $_b;
	private $_radius;
	private $_image_width;
	private $_image_height;
	
	/**
	 *  圆度说明
	 *  可选值 0-100 ，0为不使用圆功能，1-99为圆角，100为全圆
	 *  该参数是按百分比算的，全圆的半径为宽度的一半（宽度与长度相等）
	 */

	public $round;

	/**
	 *  Indicates the file system permissions to be set for newly created images.
	 *
	 *  Better is to leave this setting as it is.
	 *
	 *  If you know what you are doing, here is how you can calculate the permission levels:
	 *
	 *  - 400 Owner Read
	 *  - 200 Owner Write
	 *  - 100 Owner Execute
	 *  - 40 Group Read
	 *  - 20 Group Write
	 *  - 10 Group Execute
	 *  - 4 Global Read
	 *  - 2 Global Write
	 *  - 1 Global Execute
	 *
	 *  Default is 0755
	 *
	 *  @var integer
	 */
	var $chmod_value;

	/**
	 *  If set to FALSE, images having both width and height smaller than the required width and height, will be left
	 *  untouched ({@link jpeg_quality} and {@link png_compression} will still apply).
	 *
	 *  Available only for the {@link resize()} method
	 *
	 *  Default is TRUE
	 *
	 *  @var boolean
	 */
	var $enlarge_smaller_images;

	/**
	 *  In case of an error read this property's value to see the error's code.
	 *
	 *  Possible error codes are:
	 *
	 *  - 1:  source file could not be found
	 *  - 2:  source file is not readable
	 *  - 3:  could not write target file
	 *  - 4:  unsupported source file format
	 *  - 5:  unsupported target file format
	 *  - 6:  GD library version does not support target file format
	 *  - 7:  GD library is not installed!
	 *  - 8:  "chmod" command is disabled via configuration
	 *
	 *  Default is 0 (no error).
	 *
	 *  @var integer
	 */
	var $error;

	/**
	 *  Indicates the quality of the output image (better quality means bigger file size).
	 *
	 *  Used only if the file at {@link target_path} is a JPG/JPEG image.
	 *
	 *  Range is 0 - 100
	 *
	 *  Default is 85
	 *
	 *  @var integer
	 */
	var $jpeg_quality;

	/**
	 *  Indicates the compression level of the output image (lower compression means bigger file size).
	 *
	 *  Available only if PHP version is 5.1.2+, and only if the file at {@link target_path} is a PNG image. It will be
	 *  ignored otherwise.
	 *
	 *  Range is 0 - 9
	 *
	 *  Default is 9
	 *
	 *  @since 2.2
	 *
	 *  @var integer
	 */
	var $png_compression;

	/**
	 *  Specifies whether, upon resizing, images should preserve their aspect ratio.
	 *
	 *  Available only for the {@link resize()} method
	 *
	 *  Default is TRUE
	 *
	 *  @var boolean
	 */
	var $preserve_aspect_ratio;

	/**
	 *  Indicates whether a target files should preserve the source file's date/time.
	 *
	 *  Default is TRUE
	 *
	 *  @since 1.0.4
	 *
	 *  @var boolean
	 */
	var $preserve_time;

	/**
	 *  Indicates whether the target image should have a "sharpen" filter applied to it.
	 *
	 *  Can be very useful when creating thumbnails and should be used only when creating thumbnails.
	 *
	 *  <i>The sharpen filter relies on the "imageconvolution" PHP function which is available only for PHP version
	 *  5.1.0+, and will leave the images unaltered for older versions!</i>
	 *
	 *  Default is FALSE
	 *
	 *  @since 2.2
	 *
	 *  @var boolean
	 */
	var $sharpen_images;

	/**
	 *  Path to an image file to apply the transformations to.
	 *
	 *  Supported file types are <b>GIF</b>, <b>PNG</b> and <b>JPEG</b>.
	 *
	 *  @var    string
	 */
	var $source_path;

	/**
	 *  Path (including file name) to where to save the transformed image.
	 *
	 *  <i>Can be a different than {@link source_path} - the type of the transformed image will be as indicated by the
	 *  file's extension (supported file types are GIF, PNG and JPEG)</i>.
	 *
	 *  @var    string
	 */
	var $target_path;

	/**
	 *  Constructor of the class.
	 *
	 *  Initializes the class and the default properties
	 *
	 *  @return void
	 */
	function Zebra_Image()
	{

		// set default values for properties
		$this->chmod_value = 0755;

		$this->error = 0;

		$this->jpeg_quality = 85;

		$this->png_compression = 9;

		$this->preserve_aspect_ratio = $this->preserve_time = $this->enlarge_smaller_images = true;

		$this->sharpen_images = false;

		$this->source_path = $this->target_path = '';

	}

	/**
	 *  Applies one or more filters to the image given as {@link source_path} and outputs it as the file specified as
	 *  {@link target_path}.
	 *
	 *  <samp>This method is available only if the {@link http://php.net/manual/en/function.imagefilter.php imagefilter}
	 *  function is available (available from PHP 5+), and will leave images unaltered otherwise.</samp>
	 *
	 *  <code>
	 *  // include the Zebra_Image library
	 *  require 'path/to/Zebra_Image.php';
	 *
	 *  // instantiate the class
	 *  $img = new Zebra_Image();
	 *
	 *  // a source image
	 *  $img->source_path = 'path/to/source.ext';
	 *
	 *  // path to where should the resulting image be saved
	 *  // note that by simply setting a different extension to the file will
	 *  // instruct the script to create an image of that particular type
	 *  $img->target_path = 'path/to/target.ext';
	 *
	 *  // apply the "grayscale" filter
	 *  $img->apply_filter('grayscale');
	 *
	 *  // apply the "contrast" filter
	 *  $img->apply_filter('contrast', -20);
	 *  </code>
	 *
	 *  You can also apply multiple filters at once. In this case, the method requires a single argument, an array of
	 *  arrays, containing the filters and associated arguments, where applicable:
	 *
	 *  <code>
	 *  // create a sepia effect
	 *  // note how we're applying multiple filters at once
	 *  // each filter is in its own array
	 *  $img->apply_filter(array(
	 *
	 *      // first we apply the "grayscale" filter
	 *      array('grayscale'),
	 *
	 *      // then we apply the "colorize" filter with 90, 60, 40 as
	 *      // the values for red, green and blue
	 *      array('colorize', 90, 60, 40),
	 *
	 *  ));
	 *  </code>
	 *
	 *  @param  string  $filter     The (case-insensitive) name of the filter to apply. Can be one of the following:
	 *
	 *                              -   <b>brightness</b>       -   changes the brightness of the image; use <b>arg1</b>
	 *                                                              to set the level of brightness; the range of brightness
	 *                                                              is -255 to 255;
	 *                              -   <b>colorize</b>         -   adds (subtracts) specified RGB values to each pixel;
	 *                                                              use <b>arg1</b>, <b>arg2</b> and <b>arg3</b> in the
	 *                                                              form of red, green, blue and <b>arg4</b> for the alpha
	 *                                                              channel. the range for each color is -255 to 255 and
	 *                                                              0 to 127 for alpha; <i>alpha support is available only
	 *                                                              for PHP 5.2.5+</i>;
	 *                              -   <b>contrast</b>         -   changes the contrast of the image; use <b>arg1</b>
	 *                                                              to set the level of contrast; the range of contrast
	 *                                                              is -100 to 100;
	 *                              -   <b>gausian_blur</b>     -   blurs the image using the Gaussian method;
	 *                              -   <b>grayscale</b>        -   converts the image into grayscale;
	 *                              -   <b>edgedetect</b>       -   uses edge detection to highlight the edges in the image;
	 *                              -   <b>emboss</b>           -   embosses the image;
	 *                              -   <b>mean_removal</b>     -   uses mean removal to achieve a "sketchy" effect;
	 *                              -   <b>negate</b>           -   reverses all the colors of the image;
	 *                              -   <b>pixelate</b>         -   applies pixelation effect to the image, use <b>arg1</b>
	 *                                                              to set the block size and <b>arg2</b> to set the
	 *                                                              pixelation effect mode; <i>this filter is available
	 *                                                              only for PHP 5.3.0+</i>;
	 *                              -   <b>selective_blur</b>   -   blurs the image;
	 *                              -   <b>smooth</b>           -   makes the image smoother. Use <b>arg1</b> to set the
	 *                                                              level of smoothness. applies a 9-cell convolution matrix
	 *                                                              where center pixel has the weight of <b>arg1</b> and
	 *                                                              others weight of 1.0. the result is normalized by dividing
	 *                                                              the sum with <b>arg1</b> + 8.0 (sum of the matrix).
	 *                                                              any float is accepted;
	 *
	 *  @param  mixed   $arg1       Used by the following filters:
	 *                              -   <b>brightness</b>       -   sets the brightness level (-255 to 255)
	 *                              -   <b>contrast</b>         -   sets the contrast level (-100 to 100)
	 *                              -   <b>colorize</b>         -   sets the value of the red component (-255 to 255)
	 *                              -   <b>smooth</b>           -   sets the smoothness level
	 *                              -   <b>pixelate</b>         -   sets the block size, in pixels
	 *
	 *  @param  mixed   $arg2       Used by the following filters:
	 *                              -   <b>colorize</b>         -   sets the value of the green component (-255 to 255)
	 *                              -   <b>pixelate</b>         -   whether to use advanced pixelation effect or not (defaults to FALSE).
	 *
	 *  @param  mixed   $arg3       Used by the following filters:
	 *                              -   <b>colorize</b>         -   sets the value of the blue component (-255 to 255)
	 *
	 *  @param  mixed   $arg4       Used by the following filters:
	 *                              -   <b>colorize</b>         -   alpha channel; a value between 0 and 127. 0 indicates
	 *                                                              completely opaque while 127 indicates completely
	 *                                                              transparent.
	 *
	 *  @since 2.2.2
	 *
	 *  @return boolean             Returns TRUE on success or FALSE on error.
	 *
	 *                              If {@link http://php.net/manual/en/function.imagefilter.php imagefilter} is not
	 *                              available the method will return FALSE without setting an {@link error} code.
	 *
	 *                              If the requested filter doesn't exist, or invalid arguments are passed, the method
	 *                              will trigger a warning.
	 *
	 *                              If FALSE is returned and you are sure that
	 *                              {@link http://php.net/manual/en/function.imagefilter.php imagefilter} exists and that
	 *                              the requested filter is valid, check the {@link error} property to see the error code.
	 */
	function apply_filter($filter, $arg1 = '', $arg2 = '', $arg3 = '', $arg4 = '')
	{

		// if "imagefilter" function exists and the requested filter exists
		if (function_exists('imagefilter'))

			// if image resource was successfully created
			if ($this->_create_from_source()) {

				// prepare the target image
				$target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1);

				// copy the original image
				imagecopyresampled(

					$target_identifier,
					$this->source_identifier,
					0,
					0,
					0,
					0,
					$this->source_width,
					$this->source_height,
					$this->source_width,
					$this->source_height

				);

				// if multiple filters are to be applied at once
				if (is_array($filter)) {

					// iterate through the filters
					foreach ($filter as $arguments)

						// if filter exists
						if (defined('IMG_FILTER_' . strtoupper($arguments[0]))) {

							// try to apply the filter...
							if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($arguments[0]))), array_slice($arguments, 1))))

								// ...and trigger an error if the filter could not be applied
								trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING);

						// if filter doesn't exists, trigger an error
						} else trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING);

				// if a single filter is to be applied and it is available
				} elseif (defined('IMG_FILTER_' . strtoupper($filter))) {

					// get all the arguments passed to the method
					$arguments = func_get_args();

					// try to apply the filter...
					if (!@call_user_func_array('imagefilter', array_merge(array($target_identifier, constant('IMG_FILTER_' . strtoupper($filter))), array_slice($arguments, 1))))

						// ...and trigger an error if the filter could not be applied
						trigger_error('Invalid arguments used for "' . strtoupper($arguments[0]) . '" filter', E_USER_WARNING);

				// if filter doesn't exists, trigger an error
				} else trigger_error('Filter "' . strtoupper($arguments[0]) . '" is not available', E_USER_WARNING);

				// write image
				return $this->_write_image($target_identifier);

			}

		// if script gets this far, return false
		// note that we do not set the error level as it has been already set
		// by the _create_from_source() method earlier, if the case
		return false;

	}

	/**
	 *  Crops a portion of the image given as {@link source_path} and outputs it as the file specified as {@link target_path}.
	 *
	 *  <code>
	 *  // include the Zebra_Image library
	 *  require 'path/to/Zebra_Image.php';
	 *
	 *  // instantiate the class
	 *  $img = new Zebra_Image();
	 *
	 *  // a source image
	 *  $img->source_path = 'path/to/source.ext';
	 *
	 *  // path to where should the resulting image be saved
	 *  // note that by simply setting a different extension to the file will
	 *  // instruct the script to create an image of that particular type
	 *  $img->target_path = 'path/to/target.ext';
	 *
	 *  // crop a rectangle of 100x100 pixels, starting from the top-left corner
	 *  $img->crop(0, 0, 100, 100);
	 *  </code>
	 *
	 *  @param  integer     $start_x    x coordinate to start cropping from
	 *
	 *  @param  integer     $start_y    y coordinate to start cropping from
	 *
	 *  @param  integer     $end_x      x coordinate where to end the cropping
	 *
	 *  @param  integer     $end_y      y coordinate where to end the cropping
	 *
	 *  @since  1.0.4
	 *
	 *  @return boolean     Returns TRUE on success or FALSE on error.
	 *
	 *                      If FALSE is returned, check the {@link error} property to see the error code.
	 */
	function crop($start_x, $start_y, $end_x, $end_y)
	{

		// this method might be also called internally
		// in this case, there's a fifth argument that points to an already existing image identifier
		$args = func_get_args();

		// if fifth argument exists
		if (isset($args[4]) && is_resource($args[4])) {

			// that it is the image identifier that we'll be using further on
			$this->source_identifier = $args[4];

			// set this to true so that the script will continue to execute at the next IF
			$result = true;

		// if method is called as usually
		// try to create an image resource from source path
		} else $result = $this->_create_from_source();

		// if image resource was successfully created
		if ($result !== false) {

			// prepare the target image
			$target_identifier = $this->_prepare_image($end_x - $start_x, $end_y - $start_y, -1);

			// crop the image
			imagecopyresampled(

				$target_identifier,
				$this->source_identifier,
				0,
				0,
				$start_x,
				$start_y,
				$end_x - $start_x,
				$end_y - $start_y,
				$end_x - $start_x,
				$end_y - $start_y

			);

			// write image
			return $this->_write_image($target_identifier);

		}

		// if script gets this far, return false
		// note that we do not set the error level as it has been already set
		// by the _create_from_source() method earlier
		return false;

	}

	/**
	 *  Flips both horizontally and vertically the image given as {@link source_path} and outputs the resulted image as
	 *  {@link target_path}
	 *
	 *  <code>
	 *  // include the Zebra_Image library
	 *  require 'path/to/Zebra_Image.php';
	 *
	 *  // instantiate the class
	 *  $img = new Zebra_Image();
	 *
	 *  // a source image
	 *  $img->source_path = 'path/to/source.ext';
	 *
	 *  // path to where should the resulting image be saved
	 *  // note that by simply setting a different extension to the file will
	 *  // instruct the script to create an image of that particular type
	 *  $img->target_path = 'path/to/target.ext';
	 *
	 *  // flip the image both horizontally and vertically
	 *  $img->flip_both();
	 *  </code>
	 *
	 *  @since 2.1
	 *
	 *  @return boolean     Returns TRUE on success or FALSE on error.
	 *
	 *                      If FALSE is returned, check the {@link error} property to see the error code.
	 */
	function flip_both()
	{

		return $this->_flip('both');

	}

	/**
	 *  Flips horizontally the image given as {@link source_path} and outputs the resulted image as {@link target_path}
	 *
	 *  <code>
	 *  // include the Zebra_Image library
	 *  require 'path/to/Zebra_Image.php';
	 *
	 *  // instantiate the class
	 *  $img = new Zebra_Image();
	 *
	 *  // a source image
	 *  $img->source_path = 'path/to/source.ext';
	 *
	 *  // path to where should the resulting image be saved
	 *  // note that by simply setting a different extension to the file will
	 *  // instruct the script to create an image of that particular type
	 *  $img->target_path = 'path/to/target.ext';
	 *
	 *  // flip the image horizontally
	 *  $img->flip_horizontal();
	 *  </code>
	 *
	 *  @return boolean     Returns TRUE on success or FALSE on error.
	 *
	 *                      If FALSE is returned, check the {@link error} property to see the error code.
	 */
	function flip_horizontal()
	{

		return $this->_flip('horizontal');

	}

	/**
	 *  Flips vertically the image given as {@link source_path} and outputs the resulted image as {@link target_path}
	 *
	 *  <code>
	 *  // include the Zebra_Image library
	 *  require 'path/to/Zebra_Image.php';
	 *
	 *  // instantiate the class
	 *  $img = new Zebra_Image();
	 *
	 *  // a source image
	 *  $img->source_path = 'path/to/source.ext';
	 *
	 *  // path to where should the resulting image be saved
	 *  // note that by simply setting a different extension to the file will
	 *  // instruct the script to create an image of that particular type
	 *  $img->target_path = 'path/to/target.ext';
	 *
	 *  // flip the image vertically
	 *  $img->flip_vertical();
	 *  </code>
	 *
	 *  @return boolean     Returns TRUE on success or FALSE on error.
	 *
	 *                      If FALSE is returned, check the {@link error} property to see the error code.
	 */
	function flip_vertical()
	{

		return $this->_flip('vertical');

	}

	/**
	 *  Resizes the image given as {@link source_path} and outputs the resulted image as {@link target_path}.
	 *
	 *  <code>
	 *  // include the Zebra_Image library
	 *  require 'path/to/Zebra_Image.php';
	 *
	 *  // instantiate the class
	 *  $img = new Zebra_Image();
	 *
	 *  // a source image
	 *  $img->source_path = 'path/to/source.ext';
	 *
	 *  // path to where should the resulting image be saved
	 *  // note that by simply setting a different extension to the file will
	 *  // instruct the script to create an image of that particular type
	 *  $img->target_path = 'path/to/target.ext';
	 *
	 *  // apply a "sharpen" filter to the resulting images
	 *  $img->sharpen_images = true;
	 *
	 *  // resize the image to exactly 150x150 pixels, without altering aspect ratio, by using the CROP_CENTER method
	 *  $img->resize(150, 150, ZEBRA_IMAGE_CROP_CENTER);
	 *  </code>
	 *
	 *  @param  integer     $width              The width to resize the image to.
	 *
	 *                                          If set to <b>0</b>, the width will be automatically adjusted, depending
	 *                                          on the value of the <b>height</b> argument so that the image preserves
	 *                                          its aspect ratio.
	 *
	 *                                          If {@link preserve_aspect_ratio} is set to TRUE and both this and the
	 *                                          <b>height</b> arguments are values greater than <b>0</b>, the image will
	 *                                          be resized to the exact required width and height and the aspect ratio
	 *                                          will be preserved - (also see the description for the <b>method</b>
	 *                                          argument below on how can this be done).
	 *
	 *                                          If {@link preserve_aspect_ratio} is set to FALSE, the image will be
	 *                                          resized to the required width and the aspect ratio will be ignored.
	 *
	 *                                          If both <b>width</b> and <b>height</b> are set to <b>0</b>, a copy of
	 *                                          the source image will be created ({@link jpeg_quality} and
	 *                                          {@link png_compression} will still apply).
	 *
	 *                                          If either <b>width</b> or <b>height</b> are set to <b>0</b>, the script
	 *                                          will consider the value of the {@link preserve_aspect_ratio} to bet set
	 *                                          to TRUE regardless of its actual value!
	 *
	 *  @param  integer     $height             The height to resize the image to.
	 *
	 *                                          If set to <b>0</b>, the height will be automatically adjusted, depending
	 *                                          on the value of the <b>width</b> argument so that the image preserves
	 *                                          its aspect ratio.
	 *
	 *                                          If {@link preserve_aspect_ratio} is set to TRUE and both this and the
	 *                                          <b>width</b> arguments are values greater than <b>0</b>, the image will
	 *                                          be resized to the exact required width and height and the aspect ratio
	 *                                          will be preserved - (also see the description for the <b>method</b>
	 *                                          argument below on how can this be done).
	 *
	 *                                          If {@link preserve_aspect_ratio} is set to FALSE, the image will be
	 *                                          resized to the required height and the aspect ratio will be ignored.
	 *
	 *                                          If both <b>width</b> and <b>height</b> are set to <b>0</b>, a copy of
	 *                                          the source image will be created ({@link jpeg_quality} and
	 *                                          {@link png_compression} will still apply).
	 *
	 *                                          If either <b>height</b> or <b>width</b> are set to <b>0</b>, the script
	 *                                          will consider the value of the {@link preserve_aspect_ratio} to bet set
	 *                                          to TRUE regardless of its actual value!
	 *
	 *  @param  int     $method                 (Optional) Method to use when resizing images to exact width and height
	 *                                          while preserving aspect ratio.
	 *
	 *                                          If the {@link preserve_aspect_ratio} property is set to TRUE and both the
	 *                                          <b>width</b> and <b>height</b> arguments are values greater than <b>0</b>,
	 *                                          the image will be resized to the exact given width and height and the
	 *                                          aspect ratio will be preserved by using on of the following methods:
	 *
	 *                                          -   <b>ZEBRA_IMAGE_BOXED</b> - the image will be scalled so that it will
	 *                                              fit in a box with the given width and height (both width/height will
	 *                                              be smaller or equal to the required width/height) and then it will
	 *                                              be centered both horizontally and vertically. The blank area will be
	 *                                              filled with the color specified by the <b>bgcolor</b> argument. (the
	 *                                              blank area will be filled only if the image is not transparent!)
	 *
	 *                                          -   <b>ZEBRA_IMAGE_NOT_BOXED</b> - the image will be scalled so that it
	 *                                              <i>could</i> fit in a box with the given width and height but will
	 *                                              not be enclosed in a box with given width and height. The new width/
	 *                                              height will be both smaller or equal to the required width/height
	 *
	 *                                          -   <b>ZEBRA_IMAGE_CROP_TOPLEFT</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_TOPCENTER</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_TOPRIGHT</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_MIDDLELEFT</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_CENTER</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_MIDDLERIGHT</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_BOTTOMLEFT</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_BOTTOMCENTER</b>
	 *                                          -   <b>ZEBRA_IMAGE_CROP_BOTTOMRIGHT</b>
	 *
	 *                                          For the methods involving crop, first the image is scaled so that both
	 *                                          its sides are equal or greater than the respective sizes of the bounding
	 *                                          box; next, a region of required width and height will be cropped from
	 *                                          indicated region of the resulted image.
	 *
	 *                                          Default is ZEBRA_IMAGE_CROP_CENTER
	 *
	 *  @param  hexadecimal $background_color   (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the
	 *                                          blank area. See the <b>method</b> argument.
	 *
	 *                                          When set to -1 the script will preserve transparency for transparent GIF
	 *                                          and PNG images. For non-transparent images the background will be white
	 *                                          in this case.
	 *
	 *                                          Default is #FFFFFF.
	 *
	 *  @return boolean                         Returns TRUE on success or FALSE on error.
	 *
	 *                                          If FALSE is returned, check the {@link error} property to see what went
	 *                                          wrong
	 */
	function resize($width = 0, $height = 0, $method = ZEBRA_IMAGE_CROP_CENTER, $background_color = '#FFFFFF')
	{

		// if image resource was successfully created
		if ($this->_create_from_source()) {

			// if either width or height is to be adjusted automatically
			// set a flag telling the script that, even if $preserve_aspect_ratio is set to false
			// treat everything as if it was set to true
			if ($width == 0 || $height == 0) $auto_preserve_aspect_ratio = true;

			// if aspect ratio needs to be preserved
			if ($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) {

				// if height is given and width is to be computed accordingly
				if ($width == 0 && $height > 0) {

					// get the original image's aspect ratio
					$aspect_ratio = $this->source_width / $this->source_height;

					// the target image's height is as given as argument to the method
					$target_height = $height;

					// compute the target image's width, preserving the aspect ratio
					$target_width = round($height * $aspect_ratio);

				// if width is given and height is to be computed accordingly
				} elseif ($width > 0 && $height == 0) {

					// get the original image's aspect ratio
					$aspect_ratio = $this->source_height / $this->source_width;

					// the target image's width is as given as argument to the method
					$target_width = $width;

					// compute the target image's height, preserving the aspect ratio
					$target_height = round($width * $aspect_ratio);

				// if both width and height are given and ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED methods are to be used
				} elseif ($width > 0 && $height > 0 && ($method == 0 || $method == 1)) {

					// compute the horizontal and vertical aspect ratios
					$vertical_aspect_ratio = $height / $this->source_height;
					$horizontal_aspect_ratio = $width / $this->source_width;

					// if the image's newly computed height would be inside the bounding box
					if (round($horizontal_aspect_ratio * $this->source_height < $height)) {

						// the target image's width is as given as argument to the method
						$target_width = $width;

						// compute the target image's height so that the image will stay inside the bounding box
						$target_height = round($horizontal_aspect_ratio * $this->source_height);

					// otherwise
					} else {

						// the target image's height is as given as argument to the method
						$target_height = $height;

						// compute the target image's width so that the image will stay inside the bounding box
						$target_width = round($vertical_aspect_ratio * $this->source_width);

					}

				// if both width and height are given and image is to be cropped in order to get to the required size
				} elseif ($width > 0 && $height > 0 && $method > 1 && $method < 11) {

					// compute the horizontal and vertical aspect ratios
					$vertical_aspect_ratio = $this->source_height / $height;
					$horizontal_aspect_ratio = $this->source_width /  $width;

					// we'll use one of the two
					$aspect_ratio =

						$vertical_aspect_ratio < $horizontal_aspect_ratio ?

						$vertical_aspect_ratio :

						$horizontal_aspect_ratio;

					// compute the target image's width, preserving the aspect ratio
					$target_width = round($this->source_width / $aspect_ratio);

					// compute the target image's height, preserving the aspect ratio
					$target_height = round($this->source_height / $aspect_ratio);

				// for any other case
				} else {

					// we will create a copy of the source image
					$target_width = $this->source_width;
					$target_height = $this->source_height;

				}

			// if aspect ratio does not need to be preserved
			} else {

				// compute the target image's width
				$target_width = ($width > 0 ? $width : $this->source_width);

				// compute the target image's height
				$target_height = ($height > 0 ? $height : $this->source_height);

			}

			// if
			if (

				// all images are to be resized - including images that are smaller than the given width/height
				$this->enlarge_smaller_images ||

				// smaller images than the given width/height are to be left untouched
				// but current image has at leas one side that is larger than the required width/height
				($width > 0 && $height > 0 ?

					($this->source_width > $width || $this->source_height > $height) :

					($this->source_width > $target_width || $this->source_height > $target_height)

				)

			) {

				// if
				if (

					// aspect ratio needs to be preserved AND
					($this->preserve_aspect_ratio || isset($auto_preserve_aspect_ratio)) &&

					// both width and height are given
					($width > 0 && $height > 0) &&

					// images are to be cropped
					($method > 1 && $method < 11)

				) {

					// prepare the target image
					$target_identifier = $this->_prepare_image($target_width, $target_height, $background_color);

					imagecopyresampled(

						$target_identifier,
						$this->source_identifier,
						0,
						0,
						0,
						0,
						$target_width,
						$target_height,
						$this->source_width,
						$this->source_height

					);

					// do the crop according to the required method
					switch ($method) {

						// if image needs to be cropped from the top-left corner
						case ZEBRA_IMAGE_CROP_TOPLEFT:

							// crop accordingly
							return $this->crop(
								0,
								0,
								$width,
								$height,
								$target_identifier // crop this resource instead
							);

							break;

						// if image needs to be cropped from the top-center
						case ZEBRA_IMAGE_CROP_TOPCENTER:

							// crop accordingly
							return $this->crop(
								floor(($target_width - $width) / 2),
								0,
								floor(($target_width - $width) / 2) + $width,
								$height,
								$target_identifier // crop this resource instead
							);

							break;

						// if image needs to be cropped from the top-right corner
						case ZEBRA_IMAGE_CROP_TOPRIGHT:

							// crop accordingly
							return $this->crop(
								$target_width - $width,
								0,
								$target_width,
								$height,
								$target_identifier // crop this resource instead
							);

							break;

						// if image needs to be cropped from the middle-left
						case ZEBRA_IMAGE_CROP_MIDDLELEFT:

							// crop accordingly
							return $this->crop(

								0,
								floor(($target_height - $height) / 2),
								$width,
								floor(($target_height - $height) / 2) + $height,
								$target_identifier // crop this resource instead

							);

							break;

						// if image needs to be cropped from the center of the image
						case ZEBRA_IMAGE_CROP_CENTER:

							// crop accordingly
							return $this->crop(

								floor(($target_width - $width) / 2),
								floor(($target_height - $height) / 2),
								floor(($target_width - $width) / 2) + $width,
								floor(($target_height - $height) / 2) + $height,
								$target_identifier // crop this resource instead

							);

							break;

						// if image needs to be cropped from the middle-right
						case ZEBRA_IMAGE_CROP_MIDDLERIGHT:

							// crop accordingly
							return $this->crop(

								$target_width - $width,
								floor(($target_height - $height) / 2),
								$target_width,
								floor(($target_height - $height) / 2) + $height,
								$target_identifier // crop this resource instead

							);

							break;

						// if image needs to be cropped from the bottom-left corner
						case ZEBRA_IMAGE_CROP_BOTTOMLEFT:

							// crop accordingly
							return $this->crop(

								0,
								$target_height - $height,
								$width,
								$target_height,
								$target_identifier // crop this resource instead

							);

							break;

						// if image needs to be cropped from the bottom-center
						case ZEBRA_IMAGE_CROP_BOTTOMCENTER:

							// crop accordingly
							return $this->crop(

								floor(($target_width - $width) / 2),
								$target_height - $height,
								floor(($target_width - $width) / 2) + $width,
								$target_height,
								$target_identifier // crop this resource instead

							);

							break;

						// if image needs to be cropped from the bottom-right corner
						case ZEBRA_IMAGE_CROP_BOTTOMRIGHT:

							// crop accordingly
							return $this->crop(

								$target_width - $width,
								$target_height - $height,
								$target_width,
								$target_height,
								$target_identifier // crop this resource instead

							);

							break;

					}

				// if aspect ratio doesn't need to be preserved or
				// it needs to be preserved and method is ZEBRA_IMAGE_BOXED or ZEBRA_IMAGE_NOT_BOXED
				} else {

					// prepare the target image
					$target_identifier = $this->_prepare_image(
						($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $width : $target_width),
						($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? $height : $target_height),
						$background_color
					);

					imagecopyresampled(

						$target_identifier,
						$this->source_identifier,
						($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($width - $target_width) / 2 : 0),
						($width > 0 && $height > 0 && $method != ZEBRA_IMAGE_NOT_BOXED ? ($height - $target_height) / 2 : 0),
						0,
						0,
						$target_width,
						$target_height,
						$this->source_width,
						$this->source_height

					);

					// if script gets this far, write the image to disk
					return $this->_write_image($target_identifier);

				}

			// if we get here it means that
			// smaller images than the given width/height are to be left untouched
			// therefore, we save the image as it is
			} else return $this->_write_image($this->source_identifier);

		}

		// if script gets this far return false
		// note that we do not set the error level as it has been already set
		// by the _create_from_source() method earlier
		return false;

	}

	/**
	 *  Rotates the image given as {@link source_path} and outputs the resulted image as {@link target_path}.
	 *
	 *  <code>
	 *  // include the Zebra_Image library
	 *  require 'path/to/Zebra_Image.php';
	 *
	 *  // instantiate the class
	 *  $img = new Zebra_Image();
	 *
	 *  // a source image
	 *  $img->source_path = 'path/to/source.ext';
	 *
	 *  // path to where should the resulting image be saved
	 *  // note that by simply setting a different extension to the file will
	 *  // instruct the script to create an image of that particular type
	 *  $img->target_path = 'path/to/target.ext';
	 *
	 *  // rotate the image 45 degrees, clockwise
	 *  $img->rotate(45);
	 *  </code>
	 *
	 *  @param  double  $angle                  Angle by which to rotate the image clockwise.
	 *
	 *                                          Between 0 and 360.
	 *
	 *  @param  mixed   $background_color       (Optional) The hexadecimal color (like "#FFFFFF" or "#FFF") of the
	 *                                          uncovered zone after the rotation.
	 *
	 *                                          When set to -1 the script will preserve transparency for transparent GIF
	 *                                          and PNG images. For non-transparent images the background will be white
	 *                                          in this case.
	 *
	 *                                          Default is -1.
	 *
	 *  @return boolean                         Returns TRUE on success or FALSE on error.
	 *
	 *                                          If FALSE is returned, check the {@link error} property to see the error
	 *                                          code.
	 */
	function rotate($angle, $background_color = -1)
	{

		// if image resource was successfully created
		if ($this->_create_from_source()) {

			// angles are given clockwise but imagerotate works counterclockwise so we need to negate our value
			$angle = -$angle;

			// if source image is PNG
			if ($this->source_type == IMAGETYPE_PNG && $background_color == -1) {

				// rotate the image
				// but if using -1 as background color didn't work (as is the case for PNG8)
				if (!($target_identifier = imagerotate($this->source_identifier, $angle, -1))) {

					// we will be using #FFF as the color to fill the uncovered zone after the rotation
					$background_color = imagecolorallocate($this->source_identifier, 255, 255, 255);

					// rotate the image
					$target_identifier = imagerotate($this->source_identifier, $angle, $background_color);

				}

			// if source image is a transparent GIF
			} elseif ($this->source_type == IMAGETYPE_GIF && $this->source_transparent_color_index >= 0) {

				// convert the background color to RGB values
				$background_color = $this->_hex2rgb($background_color);

				// allocate the color to the image identifier
				$background_color = imagecolorallocate(

					$this->source_identifier,
					$background_color['r'],
					$background_color['g'],
					$background_color['b']

				);

				// rotate the image
				$this->source_identifier = imagerotate($this->source_identifier, $angle, $background_color);

				// get the width of rotated image
				$width = imagesx($this->source_identifier);

				// get the height of rotated image
				$height = imagesy($this->source_identifier);

				// create a blank image with the new width and height
				// (this intermediary step is for preserving transparency)
				$target_identifier = $this->_prepare_image($width, $height, -1);

				// copy the rotated image on to the new one
				imagecopyresampled($target_identifier, $this->source_identifier, 0, 0, 0, 0, $width, $height, $width, $height);

			// for the other cases
			} else {

				// convert the color to RGB values
				$background_color = $this->_hex2rgb($background_color);

				// allocate the color to the image identifier
				$background_color = imagecolorallocate(

					$this->source_identifier,
					$background_color['r'],
					$background_color['g'],
					$background_color['b']

				);

				// rotate the image
				$target_identifier = imagerotate($this->source_identifier, $angle, $background_color);

			}

			// write image
			$this->_write_image($target_identifier);

		}

		// if script gets this far return false
		// note that we do not set the error level as it has been already set
		// by the _create_from_source() method earlier
	   return false;

	}

	/**
	 *  Returns an array containing the image identifier representing the image obtained from {@link $source_path}, the
	 *  image's width and height and the image's type
	 *
	 *  @access private
	 */
	function _create_from_source()
	{

		// perform some error checking first
		// if the GD library is not installed
		if (!function_exists('gd_info')) {

			// save the error level and stop the execution of the script
			$this->error = 7;

			return false;

		// if source file does not exist
		} elseif (!is_file($this->source_path)) {

			// save the error level and stop the execution of the script
			$this->error = 1;

			return false;

		// if source file is not readable
		} elseif (!is_readable($this->source_path)) {

			// save the error level and stop the execution of the script
			$this->error = 2;

			return false;

		// if target file is same as source file and source file is not writable
		} elseif ($this->target_path == $this->source_path && !is_writable($this->source_path)) {

			// save the error level and stop the execution of the script
			$this->error = 3;

			return false;

		// try to get source file width, height and type
		// and if it founds an unsupported file type
		} elseif (!list($this->source_width, $this->source_height, $this->source_type) = @getimagesize($this->source_path)) {

			// save the error level and stop the execution of the script
			$this->error = 4;

			return false;

		// if no errors so far
		} else {

			// get target file's type based on the file extension
			$this->target_type = strtolower(substr($this->target_path, strrpos($this->target_path, '.') + 1));

			// create an image from file using extension dependant function
			// checks for file extension
			switch ($this->source_type) {

				// if GIF
				case IMAGETYPE_GIF:

					// create an image from file
					$identifier = imagecreatefromgif($this->source_path);

					// get the index of the transparent color (if any)
					if (($this->source_transparent_color_index = imagecolortransparent($identifier)) >= 0)

						// get the transparent color's RGB values
						// we have to mute errors because there are GIF images which *are* transparent and everything
						// works as expected, but imagecolortransparent() returns a color that is outside the range of
						// colors in the image's pallette...
						$this->source_transparent_color = @imagecolorsforindex($identifier, $this->source_transparent_color_index);

					break;

				// if JPEG
				case IMAGETYPE_JPEG:

					// create an image from file
					$identifier = imagecreatefromjpeg($this->source_path);

					break;

				// if PNG
				case IMAGETYPE_PNG:

					// create an image from file
					$identifier = imagecreatefrompng($this->source_path);

					// disable blending
					imagealphablending($identifier, false);

					break;

				default:

					// if unsupported file type
					// note that we call this if the file is not GIF, JPG or PNG even though the getimagesize function
					// handles more image types
					$this->error = 4;

					return false;

			}

		}

		// if target file has to have the same timestamp as the source image
		// save it as a global property of the class
		if ($this->preserve_time) $this->source_image_time = filemtime($this->source_path);

		// make available the source image's identifier
		$this->source_identifier = $identifier;

		return true;

	}

	/**
	 *  Converts a hexadecimal representation of a color (i.e. #123456 or #AAA) to a RGB representation.
	 *
	 *  The RGB values will be a value between 0 and 255 each.
	 *
	 *  @param  string  $color              Hexadecimal representation of a color (i.e. #123456 or #AAA).
	 *
	 *  @param  string  $default_on_error   Hexadecimal representation of a color to be used in case $color is not
	 *                                      recognized as a hexadecimal color.
	 *
	 *  @return array                       Returns an associative array with the values of (R)ed, (G)reen and (B)lue
	 *
	 *  @access private
	 */
	function _hex2rgb($color, $default_on_error = '#FFFFFF')
	{

		// if color is not formatted correctly
		// use the default color
		if (preg_match('/^#?([a-f]|[0-9]){3}(([a-f]|[0-9]){3})?$/i', $color) == 0) $color = $default_on_error;

		// trim off the "#" prefix from $background_color
		$color = ltrim($color, '#');

		// if color is given using the shorthand (i.e. "FFF" instead of "FFFFFF")
		if (strlen($color) == 3) {

			$tmp = '';

			// take each value
			// and duplicate it
			for ($i = 0; $i < 3; $i++) $tmp .= str_repeat($color[$i], 2);

			// the color in it's full, 6 characters length notation
			$color = $tmp;

		}

		// decimal representation of the color
		$int = hexdec($color);

		// extract and return the RGB values
		return array(

			'r' =>  0xFF & ($int >> 0x10),
			'g' =>  0xFF & ($int >> 0x8),
			'b' =>  0xFF & $int

		);

	}

	/**
	 *  Flips horizontally or vertically or both ways the image given as {@link source_path}.
	 *
	 *  @since 2.1
	 *
	 *  @access private
	 *
	 *  @return boolean     Returns TRUE on success or FALSE on error.
	 *
	 *                      If FALSE is returned, check the {@link error} property to see the error code.
	 */
	function _flip($orientation)
	{

		// if image resource was successfully created
		if ($this->_create_from_source()) {

			// prepare the target image
			$target_identifier = $this->_prepare_image($this->source_width, $this->source_height, -1);

			// flip according to $orientation
			switch ($orientation) {

				case 'horizontal':

					imagecopyresampled(

						$target_identifier,
						$this->source_identifier,
						0,
						0,
						($this->source_width - 1),
						0,
						$this->source_width,
						$this->source_height,
						-$this->source_width,
						$this->source_height

					);

					break;

				case 'vertical':

					imagecopyresampled(

						$target_identifier,
						$this->source_identifier,
						0,
						0,
						0,
						($this->source_height - 1),
						$this->source_width,
						$this->source_height,
						$this->source_width,
						-$this->source_height

					);

					break;

				case 'both':

					imagecopyresampled(

						$target_identifier,
						$this->source_identifier,
						0,
						0,
						($this->source_width - 1),
						($this->source_height - 1),
						$this->source_width,
						$this->source_height,
						-$this->source_width,
						-$this->source_height

					);

					break;

			}

			// write image
			return $this->_write_image($target_identifier);

		}

		// if script gets this far, return false
		// note that we do not set the error level as it has been already set
		// by the _create_from_source() method earlier
		return false;

	}

	/**
	 *  Creates a blank image of given width, height and background color.
	 *
	 *  @param  integer     $width              Width of the new image.
	 *
	 *  @param  integer     $height             Height of the new image.
	 *
	 *  @param  string      $background_color   (Optional) The hexadecimal color of the background.
	 *
	 *                                          Can also be -1 case in which the script will try to create a transparent
	 *                                          image, if possible.
	 *
	 *                                          Default is "#FFFFFF".
	 *
	 *  @return                                 Returns the identifier of the newly created image.
	 *
	 *  @access private
	 */
	function _prepare_image($width, $height, $background_color = '#FFFFFF')
	{

		// create a blank image
		$identifier = imagecreatetruecolor((int)$width <= 0 ? 1 : (int)$width, (int)$height <= 0 ? 1 : (int)$height);

		// if we are creating a PNG image
		if ($this->target_type == 'png' && $background_color == -1) {

			// disable blending
			imagealphablending($identifier, false);

			// allocate a transparent color
			$transparent_color = imagecolorallocatealpha($identifier, 0, 0, 0, 127);

			// fill the image with the transparent color
						imagefill($identifier, 0, 0, $transparent_color);

			//save full alpha channel information
						imagesavealpha($identifier, true);

		// if source image is a transparent GIF
		} elseif ($this->target_type == 'gif' && $background_color == -1 && $this->source_transparent_color_index >= 0) {

			// allocate the source image's transparent color also to the new image resource
			$transparent_color = imagecolorallocate(
				$identifier,
				$this->source_transparent_color['red'],
				$this->source_transparent_color['green'],
				$this->source_transparent_color['blue']
			);

			// fill the background of the new image with transparent color
			imagefill($identifier, 0, 0, $transparent_color);

			// from now on, every pixel having the same RGB as the transparent color will be transparent
			imagecolortransparent($identifier, $transparent_color);

		// for other image types
		} else {

			// if transparent background color specified, revert to white
			if ($background_color == -1) $background_color = '#FFFFFF';

			// convert hex color to rgb
			$background_color = $this->_hex2rgb($background_color);

			// prepare the background color
			$background_color = imagecolorallocate($identifier, $background_color['r'], $background_color['g'], $background_color['b']);

			// fill the image with the background color
			imagefill($identifier, 0, 0, $background_color);

		}

		// return the image's identifier
		return $identifier;

	}

	/**
	 *  Sharpens images. Useful when creating thumbnails.
	 *
	 *  Code taken from the comments at {@link http://docs.php.net/imageconvolution}.
	 *
	 *  <i>This function will yield a result only for PHP version 5.1.0+ and will leave the image unaltered for older
	 *  versions!</i>
	 *
	 *  @param  $identifier identifier  An image identifier
	 *
	 *  @access private
	 */
	function _sharpen_image($image)
	{

		// if the "sharpen_images" is set to true and we're running an appropriate version of PHP
		// (the "imageconvolution" is available only for PHP 5.1.0+)
		if ($this->sharpen_images && version_compare(PHP_VERSION, '5.1.0') >= 0) {

			// the convolution matrix as an array of three arrays of three floats
			$matrix = array(
				array(-1.2, -1, -1.2),
				array(-1, 20, -1),
				array(-1.2, -1, -1.2),
			);

			// the divisor of the matrix
			$divisor = array_sum(array_map('array_sum', $matrix));

			// color offset
			$offset = 0;

			// sharpen image
			imageconvolution($image, $matrix, $divisor, $offset);

		}

		// return the image's identifier
		return $image;

	}

	/**
	 *  Creates a new image from given image identifier having the extension as specified by {@link target_path}.
	 *
	 *  @param  $identifier identifier  An image identifier
	 *
	 *  @return boolean                 Returns TRUE on success or FALSE on error.
	 *
	 *                                  If FALSE is returned, check the {@link error} property to see the error code.
	 *
	 *  @access private
	 */
	function _write_image($identifier)
	{

		// sharpen image if it's required
		$this->_sharpen_image($identifier);

		if($this->round>0){
			return $this->round_it($identifier, $this->round);
		}


		// image saving process goes according to required extension
		switch ($this->target_type) {

			// if GIF
			case 'gif':

				// if GD support for this file type is not available
				// in version 1.6 of GD the support for GIF files was dropped see
				// http://php.net/manual/en/function.imagegif.php#function.imagegif.notes
				if (!function_exists('imagegif')) {

					// save the error level and stop the execution of the script
					$this->error = 6;

					return false;

				// if, for some reason, file could not be created
				} elseif (@!imagegif($identifier, $this->target_path)) {

					// save the error level and stop the execution of the script
					$this->error = 3;

					return false;

				}

				break;

			// if JPEG
			case 'jpg':
			case 'jpeg':

				// if GD support for this file type is not available
				if (!function_exists('imagejpeg')) {

					// save the error level and stop the execution of the script
					$this->error = 6;

					return false;

				// if, for some reason, file could not be created
				} elseif (@!imagejpeg($identifier, $this->target_path, $this->jpeg_quality)) {

					// save the error level and stop the execution of the script
					$this->error = 3;

					return false;

				}

				break;

			// if PNG
			case 'png':

				// save full alpha channel information
				imagesavealpha($identifier, true);

				// if GD support for this file type is not available
				if (!function_exists('imagepng')) {

					// save the error level and stop the execution of the script
					$this->error = 6;

					return false;

				// if, for some reason, file could not be created
				} elseif (@!imagepng($identifier, $this->target_path, $this->png_compression)) {

					// save the error level and stop the execution of the script
					$this->error = 3;

					return false;

				}

				break;

			// if not a supported file extension
			default:

				// save the error level and stop the execution of the script
				$this->error = 5;

				return false;

		}

		// get a list of functions disabled via configuration
		$disabled_functions = @ini_get('disable_functions');

		// if the 'chmod' function is not disabled via configuration
		if ($disabled_functions == '' || strpos('chmod', $disabled_functions) === false) {

			// chmod the file
			chmod($this->target_path, intval($this->chmod_value, 8));

		// save the error level
		} else $this->error = 8;

		// if target file has to have the same timestamp as the source image
		if ($this->preserve_time && isset($this->source_image_time)) {

			// touch the newly created file
			@touch($this->target_path, $this->source_image_time);
		}
		//处理iphone上传图片裁切后，图片旋转角度问题
		if(in_array($this->target_type, array('jpeg','jpg'))){
			$exif = exif_read_data($this->source_path);
			$ort  = $exif['Orientation'];
			switch ($ort) {
				case 3://需要旋转 180度
					$rotate = 180;
					break;
				case 6://需要旋转 90度
					$rotate = 90;
					break;
				case 8://需要旋转 90度
					$rotate = 90;
					break;
				default:
					$rotate = 0;
					break;
			}
			if($rotate > 0){
				$source_path = $this->source_path;
				$target_path = $this->target_path;
				$this->source_path = $target_path;
				// $this->target_path = $source_path;
				$this->rotate($rotate);
			}
		}

		// return true
		return true;

	}


	//以下为圆角处理方法
	
	public function _get_lt_rounder_corner() {
		$radius = $this->_radius;
		$img = imagecreatetruecolor($radius, $radius);
		$bgcolor = imagecolorallocate($img, $this->_r, $this->_g, $this->_b);
		$fgcolor = imagecolorallocate($img, 0, 0, 0);
		imagefill($img, 0, 0, $bgcolor);
		imagefilledarc($img, $radius, $radius, $radius*2, $radius*2, 180, 270, $fgcolor, IMG_ARC_PIE);
		imagecolortransparent($img, $fgcolor);
		return $img;
	}
		
	public function round_it($im, $radius, $r = 255, $g = 255, $b = 255) {  //白色透明色
	
	
	   
		$this->_r = (int)$r;
		$this->_g = (int)$g;
		$this->_b = (int)$b;
	
		// load the source image
		$src_image = $im;

		$this->_image_width = $image_width = imagesx($src_image);
		$this->_image_height = $image_height = imagesy($src_image);

		//$this->_radius = $radius;
		$this->_radius  = round($this->_image_width*$radius*0.01/2);
		
		// create a new image, with src_width, src_height, and fill it with transparent color
		$image = imagecreatetruecolor($image_width, $image_height);
		$trans_color = imagecolorallocate($image, $this->_r, $this->_g, $this->_b);
		imagefill($image, 0, 0, $trans_color);
		
		// then overwirte the source image to the new created image
		imagecopymerge($image, $src_image, 0, 0, 0, 0, $image_width, $image_height, 100);
		
		// then just copy all the rounded corner images to the 4 corners
		$radius = $this->_radius;
		// lt
		$lt_corner = $this->_get_lt_rounder_corner();
		imagecopymerge($image, $lt_corner, 0, 0, 0, 0, $radius, $radius, 100);
		// lb
		$lb_corner = imagerotate($lt_corner, 90, $trans_color);
		imagecopymerge($image, $lb_corner, 0, $image_height - $radius, 0, 0, $radius, $radius, 100);
		// rb
		$rb_corner = imagerotate($lt_corner, 180, $trans_color);
		imagecopymerge($image, $rb_corner, $image_width - $radius, $image_height - $radius, 0, 0, $radius, $radius, 100);
		// rt
		$rt_corner = imagerotate($lt_corner, 270, $trans_color);
		imagecopymerge($image, $rt_corner, $image_width - $radius, 0, 0, 0, $radius, $radius, 100);
		
		// set the transparency
		imagecolortransparent($image, $trans_color);
		// display it


		// image saving process goes according to required extension
		switch ($this->target_type) {
		// if GIF
		case 'gif':

			// if GD support for this file type is not available
			// in version 1.6 of GD the support for GIF files was dropped see
			// http://php.net/manual/en/function.imagegif.php#function.imagegif.notes
			if (!function_exists('imagegif')) {

				// save the error level and stop the execution of the script
				$this->error = 6;

				return false;

			// if, for some reason, file could not be created
			} elseif (@!imagegif($image, $this->target_path)) {

				// save the error level and stop the execution of the script
				$this->error = 3;

				return false;

			}

			break;

		// if JPEG
		case 'jpg':
		case 'jpeg':

			// if GD support for this file type is not available
			if (!function_exists('imagejpeg')) {

				// save the error level and stop the execution of the script
				$this->error = 6;

				return false;

			// if, for some reason, file could not be created
			} elseif (@!imagejpeg($image,  $this->target_path, $this->jpeg_quality)) {

				// save the error level and stop the execution of the script
				$this->error = 3;

				return false;

			}

			break;

		// if PNG
		case 'png':

			// save full alpha channel information
			//imagesavealpha($image, true);

			// if GD support for this file type is not available
			if (!function_exists('imagepng')) {

				// save the error level and stop the execution of the script
				$this->error = 6;

				return false;

			// if, for some reason, file could not be created
			} elseif (@!imagepng($image, $this->target_path, $this->png_compression)) {

				// save the error level and stop the execution of the script
				$this->error = 3;

				return false;

			}

			break;

		// if not a supported file extension
		default:

			// save the error level and stop the execution of the script
			$this->error = 5;

			return false;
		}

		// imagepng($image);
		//imagepng($image, $this->target_path, $this->png_compression);


		imagedestroy($src_image);
		imagedestroy($image);
		imagedestroy($lt_corner);
		imagedestroy($lb_corner);
		imagedestroy($rb_corner);
		imagedestroy($rt_corner);

		return true;
	}



}
?>